package com.djf.service;

import com.djf.dto.OrderUserDeliveryDTO;
import com.djf.entity.Order;
import com.djf.entity.User;
import com.djf.entity.UserDelivery;
import com.djf.mapper.OrderMapper;
import com.djf.mapper.UserDeliveryMapper;
import com.djf.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单关联查询服务
 * 实现订单、用户、配送表的应用层关联查询
 * 解决ShardingJDBC跨分片表关联查询的问题
 *
 * @author djf
 * @since 2025-01-01
 */
@Slf4j
@Service
public class OrderJoinService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserDeliveryMapper userDeliveryMapper;

    /**
     * 根据订单ID查询订单详情（包含用户和配送信息）
     *
     * @param orderId 订单ID
     * @return 订单详情DTO
     */
    public OrderUserDeliveryDTO getOrderDetailById(Long orderId) {
        log.info("查询订单详情，订单ID: {}", orderId);
        
        // 1. 查询订单信息
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            log.warn("订单不存在，订单ID: {}", orderId);
            return null;
        }
        
        // 2. 查询用户信息（广播表，直接查询）
        User user = userMapper.selectById(order.getUserId());
        
        // 3. 查询配送信息（分表，根据订单ID查询）
        UserDelivery delivery = userDeliveryMapper.getDeliveryByOrderId(orderId);
        
        // 4. 组装DTO
        return OrderUserDeliveryDTO.build(order, user, delivery);
    }

    /**
     * 根据用户ID查询用户的所有订单详情
     *
     * @param userId 用户ID
     * @return 订单详情列表
     */
    public List<OrderUserDeliveryDTO> getOrderDetailsByUserId(Long userId) {
        log.info("查询用户订单详情，用户ID: {}", userId);
        
        // 1. 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            log.warn("用户不存在，用户ID: {}", userId);
            return Collections.emptyList();
        }
        
        // 2. 查询用户的所有订单
        List<Order> orders = orderMapper.getOrdersByUserId(userId);
        if (CollectionUtils.isEmpty(orders)) {
            log.info("用户暂无订单，用户ID: {}", userId);
            return Collections.emptyList();
        }
        
        // 3. 批量查询配送信息
        List<Long> orderIds = orders.stream().map(Order::getId).collect(Collectors.toList());
        List<UserDelivery> deliveries = userDeliveryMapper.getDeliveriesByOrderIds(orderIds);
        
        // 4. 构建配送信息映射（订单ID -> 配送信息）
        Map<Long, UserDelivery> deliveryMap = deliveries.stream()
                .collect(Collectors.toMap(UserDelivery::getOrderId, Function.identity(), (v1, v2) -> v1));
        
        // 5. 组装DTO列表
        return orders.stream()
                .map(order -> OrderUserDeliveryDTO.build(order, user, deliveryMap.get(order.getId())))
                .collect(Collectors.toList());
    }

    /**
     * 根据租户ID和时间范围查询订单详情
     *
     * @param tenantId  租户ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 订单详情列表
     */
    public List<OrderUserDeliveryDTO> getOrderDetailsByTenantAndTime(Long tenantId, LocalDateTime startTime, LocalDateTime endTime) {
        log.info("查询租户订单详情，租户ID: {}, 时间范围: {} - {}", tenantId, startTime, endTime);
        
        // 1. 查询租户在指定时间范围内的订单
        List<Order> orders = orderMapper.getOrdersByTenantIdAndTimeRange(tenantId, startTime, endTime);
        if (CollectionUtils.isEmpty(orders)) {
            log.info("租户在指定时间范围内暂无订单，租户ID: {}", tenantId);
            return Collections.emptyList();
        }
        
        // 2. 获取所有用户ID和订单ID
        Set<Long> userIds = orders.stream().map(Order::getUserId).collect(Collectors.toSet());
        List<Long> orderIds = orders.stream().map(Order::getId).collect(Collectors.toList());
        
        // 3. 批量查询用户信息
        List<User> users = userMapper.getUsersByIds(new ArrayList<>(userIds));
        Map<Long, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));
        
        // 4. 批量查询配送信息
        List<UserDelivery> deliveries = userDeliveryMapper.getDeliveriesByOrderIds(orderIds);
        Map<Long, UserDelivery> deliveryMap = deliveries.stream()
                .collect(Collectors.toMap(UserDelivery::getOrderId, Function.identity(), (v1, v2) -> v1));
        
        // 5. 组装DTO列表
        return orders.stream()
                .map(order -> OrderUserDeliveryDTO.build(
                        order, 
                        userMap.get(order.getUserId()), 
                        deliveryMap.get(order.getId())
                ))
                .collect(Collectors.toList());
    }

    /**
     * 根据配送状态查询订单详情
     *
     * @param deliveryStatus 配送状态
     * @param startTime      开始时间
     * @param endTime        结束时间
     * @return 订单详情列表
     */
    public List<OrderUserDeliveryDTO> getOrderDetailsByDeliveryStatus(Integer deliveryStatus, LocalDateTime startTime, LocalDateTime endTime) {
        log.info("根据配送状态查询订单详情，配送状态: {}, 时间范围: {} - {}", deliveryStatus, startTime, endTime);
        
        // 1. 根据配送状态和时间范围查询配送记录
        List<UserDelivery> deliveries = userDeliveryMapper.getDeliveriesByStatusAndTimeRange(deliveryStatus, startTime, endTime);
        if (CollectionUtils.isEmpty(deliveries)) {
            log.info("指定配送状态和时间范围内暂无配送记录，配送状态: {}", deliveryStatus);
            return Collections.emptyList();
        }
        
        // 2. 获取所有订单ID和用户ID
        List<Long> orderIds = deliveries.stream().map(UserDelivery::getOrderId).collect(Collectors.toList());
        Set<Long> userIds = deliveries.stream().map(UserDelivery::getUserId).collect(Collectors.toSet());
        
        // 3. 批量查询订单信息
        List<Order> orders = orderMapper.getOrdersByIds(orderIds);
        Map<Long, Order> orderMap = orders.stream()
                .collect(Collectors.toMap(Order::getId, Function.identity()));
        
        // 4. 批量查询用户信息
        List<User> users = userMapper.getUsersByIds(new ArrayList<>(userIds));
        Map<Long, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));
        
        // 5. 构建配送信息映射
        Map<Long, UserDelivery> deliveryMap = deliveries.stream()
                .collect(Collectors.toMap(UserDelivery::getOrderId, Function.identity()));
        
        // 6. 组装DTO列表
        return orderIds.stream()
                .map(orderId -> {
                    Order order = orderMap.get(orderId);
                    if (order == null) return null;
                    
                    return OrderUserDeliveryDTO.build(
                            order,
                            userMap.get(order.getUserId()),
                            deliveryMap.get(orderId)
                    );
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 根据用户手机号查询订单详情
     *
     * @param phone 用户手机号
     * @return 订单详情列表
     */
    public List<OrderUserDeliveryDTO> getOrderDetailsByUserPhone(String phone) {
        log.info("根据用户手机号查询订单详情，手机号: {}", phone);
        
        // 1. 根据手机号查询用户
        User user = userMapper.getUserByPhone(phone);
        if (user == null) {
            log.warn("用户不存在，手机号: {}", phone);
            return Collections.emptyList();
        }
        
        // 2. 查询用户的订单详情
        return getOrderDetailsByUserId(user.getId());
    }

    /**
     * 根据快递单号查询订单详情
     *
     * @param trackingNumber 快递单号
     * @return 订单详情
     */
    public OrderUserDeliveryDTO getOrderDetailByTrackingNumber(String trackingNumber) {
        log.info("根据快递单号查询订单详情，快递单号: {}", trackingNumber);
        
        // 1. 根据快递单号查询配送记录
        UserDelivery delivery = userDeliveryMapper.getDeliveryByTrackingNumber(trackingNumber);
        if (delivery == null) {
            log.warn("配送记录不存在，快递单号: {}", trackingNumber);
            return null;
        }
        
        // 2. 查询订单信息
        Order order = orderMapper.selectById(delivery.getOrderId());
        
        // 3. 查询用户信息
        User user = null;
        if (order != null) {
            user = userMapper.selectById(order.getUserId());
        }
        
        // 4. 组装DTO
        return OrderUserDeliveryDTO.build(order, user, delivery);
    }
}